package com.coocaa.ops.admin.v1.upload.ftp;

import com.coocaa.ops.admin.v1.upload.exception.FtpLoginException;
import com.coocaa.ops.admin.v1.upload.ftp.model.FtpConfig;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.util.Assert;

import java.io.IOException;

/**
 * @author bijiahao
 * @date : 2019/2/14.
 * @description
 */
public abstract class AbstractFtpClient {
    /**
     * 目录分隔符
     */
    public static final String DIR_SEPRATOR = "/";

    /**
     * 客户端
     */
    protected FTPClient ftpClient;

    /**
     * 连接
     *
     * @throws IOException
     */
    protected void connect() throws IOException {
        FtpConfig ftpConfig = getFtpConfig();
        checkFtpConfig(ftpConfig);
        if (this.ftpClient == null) {
            this.ftpClient = new FTPClient();
        }
        if (this.ftpClient.isConnected()) {
            return;
        }
        ftpClient.setDataTimeout(ftpConfig.getDataTimeout());
        ftpClient.setConnectTimeout(ftpConfig.getConnectTimeout());
        ftpClient.connect(ftpConfig.getFtpHost(), ftpConfig.getPort());
        if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
            if (!ftpClient.login(ftpConfig.getUsername(), ftpConfig.getPassword())) {
                throw new FtpLoginException("Ftp login fail");
            }
        }
        //设置字符集
        ftpClient.setControlEncoding(ftpConfig.getFtpCharset());
    }

    /**
     * 校验ftp 配置
     *
     * @param ftpConfig
     */
    private void checkFtpConfig(FtpConfig ftpConfig) {
        Assert.hasText(ftpConfig.getFtpHost(), "ftp host 不能为空");
        Assert.notNull(ftpConfig.getPort(), "ftp port 不能为空");
        Assert.hasText(ftpConfig.getUsername(), "ftp username 不能为空");
        Assert.hasText(ftpConfig.getPassword(), "ftp password 不能为空");
        if (StringUtils.isBlank(ftpConfig.getFtpCharset())) {
            ftpConfig.setFtpCharset("GBK");
        }
        if (null == ftpConfig.getDataTimeout()) {
           ftpConfig.setDataTimeout(60000);
        }
        if (null == ftpConfig.getConnectTimeout()) {
            ftpConfig.setConnectTimeout(60000);
        }
    }

    /**
     * 获取ftp 配置
     *
     * @return
     */
    abstract protected FtpConfig getFtpConfig();

    public void createDirectoty(String remote) throws IOException {
        String directory = remote.substring(0, remote.lastIndexOf(DIR_SEPRATOR) + 1);
        if (isNeedCreateDir(directory)) {
            int start = remote.startsWith(DIR_SEPRATOR) ? 1 : 0;
            int end = remote.indexOf(DIR_SEPRATOR, start);
            while (true) {
                String subDir = remote.substring(start, end);
                if (!ftpClient.changeWorkingDirectory(subDir)) {
                    if (ftpClient.makeDirectory(subDir)) {
                        ftpClient.changeWorkingDirectory(subDir);
                    } else {

                    }
                }
                start = end + 1;
                end = remote.indexOf(DIR_SEPRATOR, start);
                if (end <= start) {
                    break;
                }
            }
        }
    }

    /**
     * @param fileLength
     * @return
     */
    protected int getByteSize(long fileLength) {
        if (fileLength > 500 * 1024 * 1024) {
            //超过500M
            return 1024 * 1024 * 10;

        } else if (fileLength > 50 * 1024 * 1024) {
            //超过50M
            return 1024 * 1024 * 4;

        } else if (fileLength > 10 * 1024 * 1024) {
            //超过10M
            return 1024 * 1024 * 1;

        } else if (fileLength > 3 * 1024 * 1024) {
            //超过3M
            return 1024 * 8;

        } else {
            return 1024 * 4;
        }
    }

    /**
     * 获取编码后的ftp文件路径
     *
     * @param remote
     * @return
     * @throws IOException
     */
    public String getEncodingFtpPath(String remote) throws IOException {
        return new String(remote.getBytes("GBK"), "iso-8859-1").intern();
    }


    /**
     * 是否需要创建目录
     *
     * @param remote
     * @return
     * @throws IOException
     */
    private boolean isNeedCreateDir(String remote) throws IOException {
        return !DIR_SEPRATOR.equalsIgnoreCase(remote) && !ftpClient.changeWorkingDirectory(remote);
    }


    /**
     * 关闭连接
     *
     * @throws IOException
     */
    public void disconnect(){
        if (ftpClient != null) {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
